import { resolve } from 'node:path';
import { build } from 'vite';
import { generateDeclarationFile } from './utils.js';
import { Extractor, ExtractorConfig } from '@microsoft/api-extractor';
import fs from 'node:fs';
import { mkdir, writeFile } from 'node:fs/promises';
import { existsSync } from 'node:fs';

const mode = process.argv[2] || 'production';

export default async function buildToolbarLoader() {
  // load the manifest.json from the toolbar-main build.
  const manifest = JSON.parse(
    fs.readFileSync(
      resolve(process.cwd(), 'tmp/toolbar-main/.vite/manifest.json'),
      'utf8',
    ),
  );

  const mainModules: Record<string, string> = {};
  for (const key of Object.keys(manifest)) {
    if (manifest[key].file.endsWith('.js')) {
      const lookupKey = manifest[key].file;
      mainModules[lookupKey] = fs.readFileSync(
        resolve(process.cwd(), 'tmp/toolbar-main', manifest[key].file),
        'utf8',
      );
    }
  }

  await build({
    mode: mode,
    define: {
      __MAIN_MODULES__: JSON.stringify(mainModules),
    },
    resolve: {
      alias: {
        '@': resolve(process.cwd(), 'src'),
        'tmp/toolbar-main': resolve(process.cwd(), 'tmp/toolbar-main'),
      },
      mainFields: ['module', 'main'],
      extensions: ['.mjs', '.js', '.ts', '.jsx', '.tsx', '.json'],
    },
    esbuild: {
      minifyIdentifiers: false,
      treeShaking: mode === 'production',
    },
    build: {
      outDir: resolve(process.cwd(), 'tmp/toolbar-loader'),
      commonjsOptions: {
        transformMixedEsModules: true,
        requireReturnsDefault: 'auto',
      },
      lib: {
        entry: {
          index: resolve(process.cwd(), 'src/loader.ts'),
        },
        name: 'StagewiseToolbarLoader',
        fileName: (format, entryName) => `${entryName}.${format}.js`,
        formats: ['es', 'cjs'],
      },
      sourcemap: mode === 'development' ? 'inline' : false,
      rollupOptions: {
        external: ['index.js'],
        output: {
          manualChunks: undefined,
          preserveModules: false,
        },
        treeshake: mode === 'production',
      },
      minify: mode === 'production',
      cssMinify: mode === 'production',
    },
    optimizeDeps: {
      esbuildOptions: {
        mainFields: ['module', 'main'],
      },
    },
  });

  // 确保目标目录存在
  const outDir = resolve(process.cwd(), 'tmp/toolbar-loader/unbundled-types');
  const dtsPath = resolve(outDir, 'index.d.ts');
  
  console.log(`Creating directory for toolbar-loader: ${outDir}`);
  await mkdir(outDir, { recursive: true });

  try {
    console.log('Generating declaration file for toolbar-loader...');
    generateDeclarationFile(
      {
        [resolve(process.cwd(), 'src/loader.ts')]: 'index',
      },
      outDir,
    );
    console.log('Declaration file for toolbar-loader generated successfully.');
  } catch (error) {
    console.error('Error generating declaration file for toolbar-loader:', error);
    
    // 如果声明文件生成失败，创建一个空的声明文件
    console.log(`Creating empty declaration file for toolbar-loader at ${dtsPath}`);
    await writeFile(dtsPath, `// Empty declaration file created as fallback for toolbar-loader
export interface ToolbarConfig {
  plugins?: any[];
  [key: string]: any;
}

export interface ToolbarPlugin {
  displayName: string;
  description: string;
  iconSvg: any;
  pluginName: string;
  onContextElementHover: (element: HTMLElement) => { annotation: string | null };
  onContextElementSelect: (element: HTMLElement) => { annotation: string | null };
  onPromptSend: (prompt: any) => { contextSnippets: Array<{ promptContextName: string; content: string }> | [] };
  [key: string]: any;
}

export interface SelectedElement {
  tagName: string;
  attributes: Record<string, string>;
  textContent?: string;
  ownProperties?: Record<string, any>;
  [key: string]: any;
}

export function initToolbar(config?: ToolbarConfig): void;

declare module 'index' {
  export function init(): void;
}
export {};
`);
  }

  // 确保文件存在
  if (!existsSync(dtsPath)) {
    console.log(`Declaration file for toolbar-loader not found at ${dtsPath}, creating a minimal one...`);
    await writeFile(dtsPath, `// Minimal declaration file created for toolbar-loader
export interface ToolbarConfig {
  plugins?: any[];
  [key: string]: any;
}

export interface ToolbarPlugin {
  displayName: string;
  description: string;
  iconSvg: any;
  pluginName: string;
  onContextElementHover: (element: HTMLElement) => { annotation: string | null };
  onContextElementSelect: (element: HTMLElement) => { annotation: string | null };
  onPromptSend: (prompt: any) => { contextSnippets: Array<{ promptContextName: string; content: string }> | [] };
  [key: string]: any;
}

export interface SelectedElement {
  tagName: string;
  attributes: Record<string, string>;
  textContent?: string;
  ownProperties?: Record<string, any>;
  [key: string]: any;
}

export function initToolbar(config?: ToolbarConfig): void;

declare module 'index' {
  export function init(): void;
}
export {};
`);
  } else {
    console.log(`Declaration file for toolbar-loader exists at ${dtsPath}`);
  }

  console.log('Loading API Extractor config for toolbar-loader...');
  const extractorConfig = ExtractorConfig.loadFileAndPrepare(
    resolve(process.cwd(), 'api-extractor-configs/loader.json'),
  );

  console.log('Invoking API Extractor for toolbar-loader...');
  Extractor.invoke(extractorConfig, {});
  console.log('API Extractor for toolbar-loader completed successfully.');
}
